/*
* Copyright (C) 2024-2025 Uniontech Technology Co., Ltd.
*
* Author:      zhangbingyi <zhangbingyi@uniontech.com>
*
* Maintainer:  zhangbingyi <zhangbingyi@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "scanwhitelist.h"
#include "compixmap.h"
//#include "window/dialogmanage.h"
#include "antivirus/customfiledialog.h"
#include "invokers/invokerfactory.h"
#include "common.h"
#include "comdata.h"
#include "widgets/dialogmanage.h"

//#include <DBlurEffectWidget>
#include <QLabel>
//#include <DTitlebar>
//#include <DFontSizeManager>
#include <QFileDialog>
#include <QListView>
#include <QTreeView>
#include <QDialogButtonBox>
//#include <QStandardPaths>

#define DIALOG_WIDTH 512 // dialog  宽度
#define DIALOG_MINIMUM_HEIGHT 431 // dialog  高度

#define LEFT_MARGINS 20 // 左边距
#define TOP_MARGINS 0 // 上边距
#define RIGHT_MARGINS 20 // 右边距离
#define BOTTOM_MARGINS 10 // 下边距离
#define SPACING 0 // 布局间隙

#define TABLEVIEW_WIDTH 472 // tableview 宽度
#define TABLEVIEW_HEIGHT 240 // tableview 高度
#define TABLEVIEW_ROW_HEIGHT 40 // tableview 每列高度

#define PB_CANCLE_WIDTH 170 // 取消按钮宽度
#define PB_CANCLE_HEIGHT 36 // 取消按钮高度

#define LINE_HEIGHT 28 // 分割线高度

#define TABLE_COL_ACTION 1 // table表第二列 操作

ScanWhiteList::ScanWhiteList(QWidget *parent)
    : QFrame(parent)
//    , m_blurEffect(nullptr)
    , m_pAddFileBtn(nullptr)
    , m_pCancelBtn(new QPushButton(this))
    , m_pConfirmBtn(new QPushButton(this))
    , m_whiteListTip(nullptr)
    , m_line(new QFrame(this))
    , m_tableView(nullptr)
    , m_model(nullptr)
    , m_tableWidget(nullptr)
    , m_garbageIcon(nullptr)
    , m_monitorNetFlowInvokerInter(nullptr)
    , m_deamonServiceInovokerInter(nullptr)
{
    this->setAccessibleName("scanWhiteListDialog");
    m_monitorNetFlowInvokerInter = InvokerFactory::GetInstance().CreateInvoker("com.deepin.defender.MonitorNetFlow",
                                                                               "/com/deepin/defender/MonitorNetFlow",
                                                                               "com.deepin.defender.MonitorNetFlow",
                                                                               ConnectType::SYSTEM, this);

    m_deamonServiceInovokerInter = InvokerFactory::GetInstance().CreateInvoker("com.deepin.defender.daemonservice",
                                                                               "/com/deepin/defender/daemonservice",
                                                                               "com.deepin.defender.daemonservice",
                                                                               ConnectType::SESSION, this);

    // 大小设置
    this->resize(DIALOG_WIDTH, DIALOG_MINIMUM_HEIGHT);
    this->setFixedWidth(DIALOG_WIDTH);
    this->setMinimumHeight(DIALOG_MINIMUM_HEIGHT);
    // 设置为Dialog
    setWindowFlags(Qt::Dialog);
    // 设置为阻态
    setWindowModality(Qt::ApplicationModal);
    // 背景透明化
//    setAttribute(Qt::WA_TranslucentBackground);

    // 界面初始化
    initUI();
    // 初始化数据
    initDate();

    // 删除扫描白名单
    m_monitorNetFlowInvokerInter->Connect("SendDeleteScanWhiteList", this, SLOT(deleteWhiteFile(const QString &)));
}

ScanWhiteList::~ScanWhiteList()
{
}

// 布局
void ScanWhiteList::initUI()
{
    // 主布局
    QVBoxLayout *mainlayout = new QVBoxLayout();
    setLayout(mainlayout);
//    // 背景透明化
//    m_blurEffect = new DBlurEffectWidget(this);
//    m_blurEffect->setBlendMode(DBlurEffectWidget::BehindWindowBlend);
//    // 设置模糊大小
//    m_blurEffect->resize(size());
//    m_blurEffect->lower();

    // 边距离
    mainlayout->setContentsMargins(LEFT_MARGINS - 20, TOP_MARGINS, RIGHT_MARGINS - 20, BOTTOM_MARGINS);
    mainlayout->setSpacing(SPACING);
    mainlayout->setAlignment(Qt::AlignmentFlag::AlignTop);
    QHBoxLayout *titleBarLayout = new QHBoxLayout();
    titleBarLayout->setContentsMargins(0, 0, 0, 0);

    // 右上角关闭按钮
//    DTitlebar *titleBar = new DTitlebar(this);
//    titleBar->setAccessibleName("scanWhiteListDialog_closeButton");
//    titleBar->setBackgroundTransparent(true);
//    titleBar->setTitle("");
//    titleBar->setMenuVisible(false);
//    titleBarLayout->addWidget(titleBar, 0, Qt::AlignRight | Qt::AlignTop);

//    mainlayout->addLayout(titleBarLayout);

    // 内容布局
    QVBoxLayout *contentLayout = new QVBoxLayout();
    contentLayout->setContentsMargins(LEFT_MARGINS, TOP_MARGINS, RIGHT_MARGINS, BOTTOM_MARGINS - 13);
    contentLayout->setSpacing(0);

    // 标题 白名单目录
    QLabel *label_title = new QLabel(tr("Whitelist Files"), this);
    label_title->setAccessibleName("scanWhiteListDialog_whiteLable");
    label_title->setAlignment(Qt::AlignCenter);
    QFont ft = label_title->font();
    ft.setBold(true);
    label_title->setFont(ft);
//    DFontSizeManager::instance()->bind(label_title, DFontSizeManager::T5);
    contentLayout->addWidget(label_title, 0, Qt::AlignHCenter | Qt::AlignTop);

    // 添加文件 按钮
    m_pAddFileBtn = new QCommandLinkButton(tr("Add file"));
    m_pAddFileBtn->setAccessibleName("scanWhiteListDialog_addButton");
    QHBoxLayout *btnAddLayout = new QHBoxLayout();
    btnAddLayout->addWidget(m_pAddFileBtn, 0, Qt::AlignRight);
    contentLayout->addLayout(btnAddLayout);
    connect(m_pAddFileBtn, SIGNAL(clicked()), this, SLOT(showAddFile()));

    // 中间表格布局
    QWidget *CenterWidget = new QWidget(this);
    CenterWidget->setAccessibleName("scanWhiteListDialog_centerWidget");
    CenterWidget->setMinimumWidth(TABLEVIEW_WIDTH);
    CenterWidget->setMaximumHeight(TABLEVIEW_HEIGHT - 3);
    CenterWidget->setLayout(initTableWidget());
    contentLayout->addWidget(CenterWidget, 0);

    // 提示
    QVBoxLayout *btnTipLayout = new QVBoxLayout();
    btnTipLayout->setContentsMargins(0, 0, 0, 0);
    QLabel *m_whiteListTip = new QLabel();
//    DFontSizeManager::instance()->bind(m_whiteListTip, DFontSizeManager::T8);
    m_whiteListTip->setFixedWidth(TABLEVIEW_WIDTH);
    m_whiteListTip->setAccessibleName("scanWhiteListDialog_whiteListTipLable");
    m_whiteListTip->setText(tr("Changed files will be untrusted and removed from the whitelist"));
    m_whiteListTip->setWordWrap(true);
    m_whiteListTip->setAlignment(Qt::AlignLeft);
    btnTipLayout->addSpacing(7);
    btnTipLayout->addWidget(m_whiteListTip, 0, Qt::AlignLeft);
    contentLayout->addLayout(btnTipLayout);
    contentLayout->addSpacing(20);

    // 取消按钮
    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->setAlignment(Qt::AlignHCenter);

    m_pCancelBtn->setText(tr("Cancel", "button"));
    m_pCancelBtn->setAccessibleName("scanWhiteListDialog_cancelButton");
    m_pCancelBtn->setMinimumSize(QSize(PB_CANCLE_WIDTH, PB_CANCLE_HEIGHT));
    m_pCancelBtn->setMaximumSize(QSize(PB_CANCLE_WIDTH, PB_CANCLE_HEIGHT));
    connect(m_pCancelBtn, SIGNAL(clicked()), this, SLOT(close()));

    btnLayout->addWidget(m_pCancelBtn);
    btnLayout->addSpacing(8);

    // 分割线
    m_line->setMaximumHeight(LINE_HEIGHT);
    m_line->setFrameShape(QFrame::VLine);

    btnLayout->addWidget(m_line);
    btnLayout->addSpacing(8);

    // 确认按钮
    m_pConfirmBtn->setText(tr("Confirm", "button"));
    m_pConfirmBtn->setAccessibleName("scanWhiteListDialog_confirmButton");
    m_pConfirmBtn->setMinimumSize(QSize(PB_CANCLE_WIDTH, PB_CANCLE_HEIGHT));
    m_pConfirmBtn->setMaximumSize(QSize(PB_CANCLE_WIDTH, PB_CANCLE_HEIGHT));
    m_pConfirmBtn->setAttribute(Qt::WA_NoMousePropagation);
    connect(m_pConfirmBtn, SIGNAL(clicked()), this, SLOT(acceptConfirmButtonClicked()));

    btnLayout->addWidget(m_pConfirmBtn);
    contentLayout->addLayout(btnLayout);
    mainlayout->addLayout(contentLayout);
}

// 初始化tableview
QHBoxLayout *ScanWhiteList::initTableWidget()
{
    // 表格属性设置 文件 操作
    QHBoxLayout *layout = new QHBoxLayout();
    layout->setMargin(0);
    layout->setSpacing(0);

    m_tableView = new QTableView(this);
    m_tableView->setAccessibleName("tableWidget_tableView");
    m_tableView->verticalHeader()->setDefaultSectionSize(TABLEVIEW_ROW_HEIGHT);
    m_tableView->verticalHeader()->setVisible(false);
    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 整行选中的的方式
    m_tableView->setSelectionMode(QAbstractItemView::SingleSelection); // 设置选中单个目标
    m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置禁止编辑
    m_tableView->setFrameShape(QTableView::NoFrame); // 设置无边框
    m_tableView->setShowGrid(false); // 设置不显示格子线
    m_tableView->setSortingEnabled(true); // 设置自动排序

    // 连接表格与模型
    m_model = new QStandardItemModel(this);
    m_tableView->setModel(m_model);

    // 初始化表格设置
    // 设置表头
    QStandardItem *item_0 = new QStandardItem(tr("File"));
    item_0->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    QStandardItem *item_1 = new QStandardItem(tr("Action"));
    item_1->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    m_model->setHorizontalHeaderItem(0, item_0);
    m_model->setHorizontalHeaderItem(1, item_1);

    // 设置表格样式
    m_tableWidget = new DefenderTable(this);
    m_tableWidget->setAccessibleName("centerWidget_tableWidget");
    m_tableWidget->setHeadViewSortHide(TABLE_COL_ACTION); // 隐藏下标
    m_tableWidget->setTableAndModel(m_tableView, m_model);
    layout->addWidget(m_tableWidget);

    // 设置列宽
    m_tableView->setColumnWidth(0, 401);
    m_tableView->setColumnWidth(1, 50);
    return layout;
}

// 初始化数据
void ScanWhiteList::initDate()
{
    // 获取扫描白名单
    QDBusMessage msg = DBUS_BLOCK_INVOKE(m_monitorNetFlowInvokerInter, "QueryScanWhiteList");
    GET_MESSAGE_VALUE(QStringList, rstList, msg);
    m_sScanWhiteList = rstList;

    // 不设置排序
    m_tableView->setSortingEnabled(false);
    // 隐藏排序图标
    m_tableView->horizontalHeader()->setSortIndicatorShown(false);

    for (int i = 0; i < m_sScanWhiteList.count(); ++i) {
        loadWhiteListData(m_sScanWhiteList.at(i));
    }
    // 默认隐藏排序图标，以时间逆序排序，点击表头重新显示排序图标，并以名称排序
    connect(m_tableView->horizontalHeader(),SIGNAL(sortIndicatorChanged(int, Qt::SortOrder )), this, SLOT(onSortIndicatorChanged(int, Qt::SortOrder)));
}

// 过滤白名单路径
void ScanWhiteList::filterScanWhitePath(const QString &sPath)
{
    int currentRow = m_model->rowCount();
    for (int i = 0; i < currentRow; ++i) {
        QString sData = m_model->data(m_model->index(i, 0), Qt::DisplayRole).toString();
        if (sPath == sData) {
            return;
        }
    }
    m_sTemScanWhiteList.append(sPath);
    loadWhiteListData(sPath);
}

// 加载数据
void ScanWhiteList::loadWhiteListData(QString sPath)
{
    QStandardItem *dataItem = new QStandardItem(sPath);
    dataItem->setToolTip(sPath);
    // 每次在第1行插入dataItem
    m_model->insertRow(0, dataItem);

    //为使上面加入的一行内的控件对齐
    m_model->insertRow(0, new QStandardItem);
    m_model->removeRow(0);

    // 设置第二列
    QWidget *pWidget = new QWidget(this);
    QHBoxLayout *hlayout = new QHBoxLayout;
    // setContentMargins 没设置
    QPushButton *button = new QPushButton(this);
    button->setObjectName("pbGarbage");

    // 操作显示栏
    button->setToolTip(tr("Action"));
    button->setIcon(QIcon::fromTheme(WHITE_GARBAGE_ICON).pixmap(QSize(16, 16)));

    // 操作图标大小设置
    button->setFixedSize(16, 16);
    button->setFlat(true);
    button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    hlayout->addWidget(button, 0, Qt::AlignLeft);
    pWidget->setLayout(hlayout);

    // 添加操作按钮 路径 属性
    button->setProperty("path", sPath);
    connect(button, SIGNAL(clicked()), this, SLOT(deleteFile()));
    m_tableView->setIndexWidget(m_model->index(0, 1), pWidget);
}

// 添加文件弹窗
void ScanWhiteList::showAddFile()
{
    QDBusMessage msg = DBUS_BLOCK_INVOKE(m_deamonServiceInovokerInter, "GetScanStatus");
    GET_MESSAGE_VALUE(int, status, msg);
    int currentStatus = status;
    if (ScanStatus::Scanning == ScanStatus(currentStatus)
        || ScanStatus::UsbScanning == ScanStatus(currentStatus)
        || ScanStatus::HomePageScanning == ScanStatus(currentStatus)) {
        m_pAddFileBtn->setEnabled(false);

        DialogManage dialog;
        dialog.showNormalTipDialog(IconTip, TipThreatScaning);
        return;
    }

    // 文件列表
    QFileDialog dialog;
    dialog.setFileMode(QFileDialog::ExistingFiles);
//    dialog.setAllowMixedSelection(true);
    dialog.setAcceptMode(QFileDialog::AcceptOpen);

    QString historyDir = "";
    if (historyDir.isEmpty()) {
        historyDir = QDir::homePath();
    }
    dialog.setDirectory(historyDir);
    if (QDialog::Accepted == dialog.exec()) {
        QStringList dirlist = dialog.selectedFiles();
        if (!dirlist.isEmpty()) {
            for (int i = 0; i < dirlist.count(); i++) {
                this->filterScanWhitePath(dirlist[i]);
            }
        }
    }
}

void ScanWhiteList::deleteFile()
{
    QPushButton *button = qobject_cast<QPushButton *>(sender());

    int currentRow = m_model->rowCount();
    for (int i = currentRow - 1; i >= 0; i--) {
        QString sPath = button->property("path").toString();
        QString sData = m_model->data(m_model->index(i, 0), Qt::DisplayRole).toString();
        QFileInfo info_path(sPath);
        if (info_path.isFile()) {
            if (sData == sPath) {
                m_model->removeRow(i);
                m_sTemScanWhiteList.removeOne(sData); // 同时清除列表，避免删除后继续添加

                // 安全日志
                DBUS_BLOCK_INVOKE(m_monitorNetFlowInvokerInter, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("%1 removed from the whitelist").arg(sData));
                if (m_sScanWhiteList.contains(sData)) {
                    DBUS_NOBLOCK_INVOKE(m_monitorNetFlowInvokerInter, "DeleteScanWhiteList", sData);
                }
            }
        } else {
            QFileInfo info_data(sData);
            if (info_data.isFile()) {
                sPath += "/";
            }
            if (sData.contains(sPath)) {
                m_model->removeRow(i);
                m_sTemScanWhiteList.removeOne(sData); // 同时清除列表，避免删除后继续添加

                // 安全日志
                DBUS_BLOCK_INVOKE(m_monitorNetFlowInvokerInter, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("%1 removed from the whitelist").arg(sData));
                if (m_sScanWhiteList.contains(sData)) {
                    DBUS_NOBLOCK_INVOKE(m_monitorNetFlowInvokerInter, "DeleteScanWhiteList", sData);
                }
            }
        }
    }
}

void ScanWhiteList::deleteWhiteFile(const QString &sPath)
{
    int currentRow = m_model->rowCount();
    for (int i = 0; i < currentRow; ++i) {
        QString sData = m_model->data(m_model->index(i, 0), Qt::DisplayRole).toString();
        if (sPath == sData) {
            m_model->removeRow(i);
            m_sTemScanWhiteList.removeOne(sPath);
        }
    }
}

// 接受确认按钮槽
void ScanWhiteList::acceptConfirmButtonClicked()
{
    DBUS_NOBLOCK_INVOKE(m_monitorNetFlowInvokerInter, "AddScanWhiteList", m_sTemScanWhiteList);
    for (int i = 0; i < m_sTemScanWhiteList.size(); ++i) {
        QString sPath = m_sTemScanWhiteList.at(i);
        // 安全日志
        DBUS_BLOCK_INVOKE(m_monitorNetFlowInvokerInter, "AddSecurityLog", SECURITY_LOG_TYPE_ANTIAV, tr("%1 added to the whitelist").arg(sPath));
    }

    this->close();
}

void ScanWhiteList::onSortIndicatorChanged(int logicalIndex, Qt::SortOrder order)
{
    if (0 == logicalIndex) {
        this->m_model->sort(0, order);
        m_tableView->horizontalHeader()->setSortIndicatorShown(true);
    }
}
